﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Jenvin.Library.Helper
{
    public class HashCodeHelper
    {

        //public int GetHashCode() {   
        //    int result = 17;  //任意素数   
        //    result = 31*result +c1; //c1,c2是什么看下文解释   
        //    result = 31*result +c2;   
        //    return result;
        //    /*
        //     *  其中c1，c2是我们生成的你要计算在内的字段的代码，生成规则如下：
        //        如果字段是boolean 计算为(f?1:0);
        //        如果字段是byte,char,short,int则计算为 (int)f;
        //        如果字段是long 计算为 (int)(f^(f>>32));
        //        如果字段是float 计算为 Float.floatToLongBits(f);
        //        如果字段是一个引用对象，那么直接调用对象的hashCode方法，如果需要判空，可以加上如果为空就返回0;
        //        如果字段是一个数组则需要遍历所有元素，按上面几种方法计算；
        //     * */
        //}  



        //public override int GetHashCode() { 
        //    int result = 0; 
        //    result = (result ^ 397) ^ (A == null ? 0 : A.GetHashCode()); 
        //    result = (result ^ 397) ^ (B == null ? 0 : B.GetHashCode());
        //    return result; 
        //}


        /// <summary>     
        /// Returns a hash code for the specified objects    
        ///</summary>     
        /// <param name="arr">An array of objects used for generating the hash code.</param>     
        /// <returns>     
        /// A hash code, suitable for use in hashing algorithms and data structures like a hash table.      
        /// </returns>     
        public static int GetHashCode(params object[] arr)
        {
            int hash = 0;
            foreach (var item in arr)
                hash = GetHashCodeInternal(hash, item.GetHashCode());
            return hash;
        }

        /// <summary>    
        ///  Returns a hash code for the specified objects   
        ///  </summary>  
        ///  <param name="obj1">The first object.</param>    
        ///  <param name="obj2">The second object.</param>  
        ///  <param name="obj3">The third object.</param>
        ///  <param name="obj4">The fourth object.</param>   
        ///  <returns>    
        ///  A hash code, suitable for use in hashing algorithms and data structures like a hash table. 
        ///  </returns>    
        public static int GetHashCode<T1, T2, T3, T4>(T1 obj1, T2 obj2, T3 obj3, T4 obj4)
        {
            return GetHashCode(obj1, GetHashCode(obj2, obj3, obj4));
        }

        /// <summary>  
        /// Returns a hash code for the specified objects    
        /// </summary>    
        /// <param name="obj1">The first object.</param>    
        /// <param name="obj2">The second object.</param>
        /// <param name="obj3">The third object.</param>
        /// <returns>    
        /// A hash code, suitable for use in hashing algorithms and data structures like a hash table.  
        /// </returns>

        public static int GetHashCode<T1, T2, T3>(T1 obj1, T2 obj2, T3 obj3)
        {
            return GetHashCode(obj1, GetHashCode(obj2, obj3));
        }

        /// <summary>   
        /// Returns a hash code for the specified objects    
        /// </summary>   
        /// <param name="obj1">The first object.</param>  
        /// <param name="obj2">The second object.</param>
        /// <returns>  
        /// A hash code, suitable for use in hashing algorithms and data structures like a hash table.  
        /// </returns>    

        public static int GetHashCode<T1, T2>(T1 obj1, T2 obj2)
        {
            return GetHashCodeInternal(obj1.GetHashCode(), obj2.GetHashCode());
        }

        private static int GetHashCodeInternal(int key1, int key2)
        {
            int h = key1;
            h += (h << 10);
            h ^= (h >> 6);
            h += key2;
            h += (h << 10);
            h ^= (h >> 6);
            h += (h << 3);
            h ^= (h >> 11);
            h += (h << 15);
            return h;
        }
    }

}
